#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "flv.h"
const char *infile = "haige666.flv";
const char *outfile = "chunc.flv";  
int ntoh24s(oal_uint24 * num)
{
    int value = 0;
    value += num->first<<16;
    value += num->second<<8;
    value += num->third;
    //printf("the value is [%d]\n",value);
    return value;
}
int oal_h2n_long(int num)
{
    int num1 = 0;
    int temp = 0;
    for(int i = 0 ;i < 4; i++)
    {
        temp = num>>(i*8);
        num1 += temp<<(32-(i+1)*8);
        temp = 0;
    }
    return num1;
}
int oal_n2h_long(int num)
{
    int num1 = 0;
    int temp = 0;
    for(int i = 0 ;i < 4; i++)
    {
        temp = num>>(i*8)&0xff;
        num1 += temp<<(32-(i+1)*8);
        temp = 0;
    }
    printf("num1 [%d] \n",num1);
    return num1;
}
char * find_scipt_head(char *buffer,int len)
{
    FLV_HEADER *flv_head = (FLV_HEADER *)buffer;
    int head_len = oal_n2h_long(flv_head->offset);
    printf("flv header length is [%d] \n",head_len);
    if(len < head_len)
    {
        printf("the head len is wrong\n");
        return NULL;
    }
    return (buffer + head_len);
}
char * find_vedio_head(char *script_head , int * script_len)
{
    FLVTAG_HEADER  *tag_head = (FLVTAG_HEADER *)script_head;
    int datalen = ntoh24s(&(tag_head->data_len));
    printf("the script type is [%d]\n",tag_head->tag_type);
    printf("the scripttag  data len is [%d]\n",datalen);
    *script_len = datalen + 11;
    printf("the script total len is [%d]\n",*script_len);
    VEDIO_HEAD *vedio_header = (VEDIO_HEAD *)(tag_head + 1);
    //printf("the frame type1 [%d]\n",vedio_header->frame_type);
    printf("the frame type2 [%d]\n",vedio_header->stream_id);
    AVC_HEAD *avc_header = (AVC_HEAD *)(vedio_header + 1);
    printf("the avc type is [%d]\n\n",avc_header->avc_type);
    return script_head + 15 + datalen;
}
char * find_next_vedio_head(char *last_data_head , int * tag_len , int *quit)
{
    static int frame_count = 0;
    FLVTAG_HEADER *tag_head = (FLVTAG_HEADER *)last_data_head;
    int datalen = ntoh24s(&(tag_head->data_len));
    //printf("the tag type is [%d]\n",tag_head->tag_type);
    //printf("the vedio  data len is [%d]\n",datalen);
    *tag_len = datalen + 11;
    //printf("the vedio total len is [%d]\n",*tag_len);
    VEDIO_HEAD *vedio_header = (VEDIO_HEAD *)(tag_head + 1);
    //printf("the frame type1 [%d]\n",vedio_header->frame_type);
    //printf("the frame type2 [%d]\n",vedio_header->vedio_header);
    AVC_HEAD *avc_header = (AVC_HEAD *)(vedio_header + 1);
    //printf("the avc type is [%d]\n\n",avc_header->avc_type);
    frame_count ++;
    if( frame_count > 4 && vedio_header->stream_id == 1 )
    {
         printf("frame_count [%d]\n",frame_count);
         *quit = 1;
    }
    return last_data_head + 15 + datalen;
}
int do_tunc(char *buffer , int buffer_len)
{
    int meta_len = 0;
    char *script_head = find_scipt_head(buffer,buffer_len);
    if(script_head == NULL)
    {
        return -1;
    }
    int script_tag_len = 0;
    char *vedio_data = find_vedio_head(script_head,&script_tag_len);
    vedio_data = find_vedio_head(vedio_data,&script_tag_len);
    printf("___________________________\n");
    meta_len = vedio_data - buffer;
    int tag_len;
    int flag = 400;
    char *next_vedio_tag = vedio_data;
    //char *end_tag_head;
    int quit = 0;
    while(flag-- != 0)
    {
        char *last_tag = next_vedio_tag;
        next_vedio_tag = find_next_vedio_head(next_vedio_tag,&tag_len , &quit);
        if(quit)
        {
            //end_tag_head = next_vedio_tag;
            //printf("break, the buffer [%p] , the end [%p]\n",buffer + buffer_len , next_vedio_tag);
            next_vedio_tag = last_tag;
            break;
        }
    }
    //end_tag_head = next_vedio_tag;
    //next_vedio_tag = vedio_data;
    FLVTAG_HEADER *new_vedio_head = (FLVTAG_HEADER *)next_vedio_tag;
    new_vedio_head->PreviousTagSize = oal_h2n_long(script_tag_len);
    printf("script tag len is [%d]!\n",oal_n2h_long(new_vedio_head->PreviousTagSize));
    int fd = open(outfile,O_CREAT|O_RDWR);
    if(fd < 0)
    {
        printf("cnnot open out file!\n");
        return -1;
    }
    int ret = 0;
    int write_len = 0;
    do
    {
        ret = write(fd,buffer + write_len ,meta_len - write_len);
        write_len += ret;
    }while(meta_len > write_len);
    //int end_len = buffer_len - (end_tag_head - buffer);
    int left_len = buffer_len - (next_vedio_tag - buffer);
    write_len = 0;
    int repeat = 1;
    while(repeat -- > 0)
    {
        do
        {
            ret = write(fd,next_vedio_tag + write_len ,left_len - write_len);
            write_len += ret;
        } while (left_len > write_len);
        write_len = 0;
        printf("write !!!\n");
    }
    // write_len = 0;
    // do
    // {
    //     ret = write(fd,end_tag_head + write_len ,end_len - write_len);
    //     write_len += ret;
    // } while (end_len > write_len);

    close(fd);
    printf("write ok!!!\n");
    return 0;
}
int main()
{
    FILE* fp; 
	char *p;
	fp = fopen(infile,"rb");// localfile文件名  
	if(fp == NULL)
	{
		printf("the file is not exsit\n");
		return -1;
	}	      
	fseek(fp,0L,SEEK_END); /* 定位到文件末尾 */  
	int flen = ftell(fp); /* 得到文件大小 */  
	//oal_print("the file len is [%u]\n",flen);
	p = (char *)malloc(flen); /* 根据文件大小动态分配内存空间 */  
	if(p==NULL)  
	{  
		fclose(fp);  
		printf("malloc failed\n");
		return -1;
	}  
	fseek(fp,0L,SEEK_SET); /* 定位到文件开头 */  
	fread(p,1,flen,fp); /* 一次性读取全部文件内容 */  
	fclose(fp);
/*
函数名: fread
功  能: 从一个流中读数据
用  法: int fread(void *ptr, int size, int nitems, FILE *stream);
参  数：用于接收数据的地址（ptr） 
        单个元素的大小（size） 
        元素个数（nitems）
        提供数据的文件指针（stream）
返回值：成功读取的元素个数
程序例:
*/
	if(do_tunc(p,flen) < 0)
    {
        printf("do tunc failed\n");
    }
    free(p);
	return 0;  
}